package com.zy.explore.common.infrastructure.util;

import com.google.common.collect.Lists;
import com.zy.explore.common.infrastructure.exception.BaseException;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 日期工具类补充
 *
 * @author ChinaYin  主页:https://gitee.com/zy-explorej2ee 邮箱:zyexplorej2ee@sina.com
 * @date 2021年06月13日 19:39:10
 */
public class MyDateUtil {

    /** yyyy/MM/dd格式 */
    public static final String SHORT_PATTERN_1 = "yyyy/MM/dd";

    /** 时间格式(yyyy-MM-dd) */
    public final static String SHORT_PATTERN_2 = "yyyy-MM-dd";

    /** yyyy.MM.dd格式 */
    public static final String SHORT_PATTERN_3 = "yyyy.MM.dd";

    /** yy_MM_dd格式 */
    public static final String SHORT_PATTERN_4 = "yy_MM_dd";

    public static final String SHORT_PATTERN_5 = "HH:mm";

    /** yyyy/MM/dd HH:mm:ss格式 */
    public static final String NORMAL_PATTERN_1 = "yyyy/MM/dd HH:mm:ss";

    /** 时间格式(yyyy-MM-dd HH:mm:ss) */
    public final static String NORMAL_PATTERN_2 = "yyyy-MM-dd HH:mm:ss";

    /** yyyy.MM.dd HH:mm:ss 格式 */
    public static final String NORMAL_PATTERN_3 = "yyyy.MM.dd HH:mm:ss";

    private MyDateUtil() {}

    /**
     * 获取过去7天内的日期数组
     * @param intervals      intervals天内
     * @return              日期数组
     */
    public static List<String> getDateList(int intervals) {
        List<String> pastDaysList = Lists.newArrayList();
        for (int i = intervals -1; i >= 0; i--) {
            pastDaysList.add(getPastDate(i));
        }
        return pastDaysList;
    }

    /**
     * 获取过去第几天的日期
     * @param pastN 过去N天
     * @return 返回日期串 yyyy-MM-dd
     */
    public static String getPastDate(int pastN) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - pastN);
        Date today = calendar.getTime();
        SimpleDateFormat format = new SimpleDateFormat(MyDateUtil.SHORT_PATTERN_2);
        return format.format(today);
    }

    public static String format(Date date) {
        return format(date, SHORT_PATTERN_2);
    }

    public static String format(Date date, String pattern) {
        if(date != null){
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            return df.format(date);
        }
        return null;
    }

    public static String getBeginDateStr(int year, int month) {
        YearMonth yearMonth = YearMonth.of(year, month);
        LocalDate localDate = yearMonth.atDay(1);
        LocalDateTime startOfDay = localDate.atStartOfDay();
        ZonedDateTime zonedDateTime = startOfDay.atZone(ZoneId.of("Asia/Shanghai"));

        return MyDateUtil.formatDate(Date.from(zonedDateTime.toInstant()), MyDateUtil.SHORT_PATTERN_2);
    }

    public static String getEndDateStr(int year, int month) {
        YearMonth yearMonth = YearMonth.of(year, month);
        LocalDate endOfMonth = yearMonth.atEndOfMonth();
        LocalDateTime localDateTime = endOfMonth.atTime(23, 59, 59, 999);
        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.of("Asia/Shanghai"));
        return MyDateUtil.formatDate(Date.from(zonedDateTime.toInstant()), MyDateUtil.SHORT_PATTERN_2);
    }

    /**
     * 获取距离当前日期前/后 n 天的日期
     *
     * @param n 传正数表示n天后，传负数表示n天前
     * @return
     */
    public static Date getDate(int n) {
        //计算n天前/后的日期
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.add(Calendar.DATE, n);
        return cal.getTime();
    }

    /**
     * 获取距离给定日期前/后 n 天的日期
     *
     * @param n 传正数表示n天后，传负数表示n天前
     * @return
     */
    public static Date getDate(Date date, int n) {
        //计算昨天的日期
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, n);
        return cal.getTime();
    }

    /**
     * 格式化日期
     *
     * @param date
     * @param pattern
     * @return
     */
    public static String formatDate(Date date, String pattern) {
        return new SimpleDateFormat(pattern).format(date);
    }

    /**
     * 将日期字符串按给定格式解析为日期
     *
     * @param dateStr
     * @param pattern
     * @return
     * @throws Exception
     */
    public static Date parseDate(String dateStr, String pattern) throws Exception {
        return new SimpleDateFormat(pattern).parse(dateStr);
    }

    /**
     * 计算两个日期间一共有多少天(包括起始时间，即算头也算尾)
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int calcBetweenDays(Date date1, Date date2) {
        long betweenDays = (date1.getTime() - date2.getTime()) / (1000 * 3600 * 24);
        return Math.abs((int) betweenDays);
    }

    /**
     * 根据前端参数获取对应的日期集合
     *
     * @param dateType  1.今天 2.昨天 3.最近7天 4.最近30天 5.自定义范围
     * @param dateRange 类型为5时，必传
     * @param max       最大间隔天数
     * @return
     * @throws Exception
     */
    public static List<String> getDateList(Integer dateType, String dateRange, Integer max) {
        List<String> dateList = Lists.newArrayList();
        Date date;
        switch (dateType) {
            // 默认返回 今天
            default:
                date = MyDateUtil.getDate(0);
                dateList.add(MyDateUtil.formatDate(date, MyDateUtil.SHORT_PATTERN_2));
                break;
            // 昨天
            case 2:
                date = MyDateUtil.getDate(-1);
                dateList.add(MyDateUtil.formatDate(date, MyDateUtil.SHORT_PATTERN_2));
                break;

            // 最近7天
            case 3:
                int recentSevenDay = 6;
                for (int i = recentSevenDay; i >= 0; i--) {
                    date = MyDateUtil.getDate(-i);
                    dateList.add(MyDateUtil.formatDate(date, MyDateUtil.SHORT_PATTERN_2));
                }
                break;

            // 最近30天
            case 4:
                int recentMonth = 29;
                for (int i = recentMonth; i >= 0; i--) {
                    date = MyDateUtil.getDate(-i);
                    dateList.add(MyDateUtil.formatDate(date, MyDateUtil.SHORT_PATTERN_2));
                }
                break;

            // 选择时间段
            case 5:
                String[] dateRangeArr = dateRange.split("~");
                Date startDate = null;
                Date endDate = null;
                try {
                    String backslash = "/";
                    String horizontalBar = "-";
                    if (dateRange.contains(backslash)) {
                        startDate = MyDateUtil.parseDate(dateRangeArr[0], MyDateUtil.SHORT_PATTERN_1);
                        endDate = MyDateUtil.parseDate(dateRangeArr[1], MyDateUtil.SHORT_PATTERN_1);
                    } else if (dateRange.contains(horizontalBar)) {
                        startDate = MyDateUtil.parseDate(dateRangeArr[0], MyDateUtil.SHORT_PATTERN_2);
                        endDate = MyDateUtil.parseDate(dateRangeArr[1], MyDateUtil.SHORT_PATTERN_2);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (startDate == null || endDate == null) {
                    return dateList;
                }
                // 检验手动输入的两个日期差值是否超过90天
                int betweenDays = MyDateUtil.calcBetweenDays(startDate, endDate);
                if (betweenDays > max || betweenDays < 0) {
                    throw new BaseException(400, "日期范围超限");
                }
                for (int i = betweenDays; i >= 0; i--) {
                    date = MyDateUtil.getDate(endDate, -i);
                    dateList.add(MyDateUtil.formatDate(date, MyDateUtil.SHORT_PATTERN_2));
                }
                break;
        }
        return dateList;
    }

}
